home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 1 / PC World Interactive 1 - Nisan 1997.iso / nostalji / bbs / modem / telix.arj / QDHOST.SLT < prev    next >
Text File  |  1993-02-05  |  29KB  |  1,100 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //   Q D H O S T . S L T
  4. //
  5. //   Copyright (C) 1988-1992 deltaComm Development.
  6. //
  7. //   - Written by Colin Sampaleanu.
  8. //   - Modifications by Jeff Woods, Feb '91, to add help function and support
  9. //     for locked modems.
  10. //   - Modifications by Dan Horn, Nov '92, fixed 'floating' timer bug.
  11. //
  12. //
  13. //   This is a Host Mode for Telix, written as a script file.
  14. //   To configure Host Mode parameters such as passwords, run the 'QDCONFIG'
  15. //   script. That script is run automatically if the Host Mode configuration
  16. //   file 'QDHOST.CNF' is missing.
  17. //
  18. //   This script will only work with Hayes compatible modems, but may be
  19. //   modified for operation with other modems.
  20. //
  21. //////////////////////////////////////////////////////////////////////////////
  22.  
  23. // Parameters which can be configured
  24.  
  25. str pass1[8] = "pass1",                 // The level 1 pass
  26.     pass2[8] = "pass2",                 // The level 2 (Sysop) pass
  27.     shellpass[8] = "shell",             // the pass to enter the Remote Shell
  28.     shutpass[8] = "shut",               // the pass to shut down the Host Mode
  29.     host_downloads[64],                 // where users may download from
  30.     host_uploads[64];                   // where uploaded files go
  31. int direct_connect = 0,
  32.     modem_lock = 0;
  33.  
  34. str current_caller[31],                 // storage of current caller's name
  35.     conn300[] = "CONNECT^M",            // modem result messages for bauds
  36.     conn1200[] = "CONNECT 1200",
  37.     conn2400[] = "CONNECT 2400",
  38.     conn9600[] = "CONNECT 9600",
  39.     conn19200[] = "CONNECT 19200";
  40.  
  41. int finished_caller,                    // set to TRUE when must return to top
  42.     local_mode,                         // set to TRUE when local test mode
  43.     access_level,                       // access level of current caller
  44.     carrier_counts = 1,                 // TRUE if should watch Carrier signal
  45.     already_connected = 0,
  46.     exit_requested = 0,                 // set to TRUE if Sysop has pressed Esc
  47.     connection_lost = 0,                // set to TRUE when carrier lost
  48.     kill_user = 0;                      // set to TRUE when user must be purged
  49.  
  50. int old_scr_chk_key,                    // storage for some system variables
  51.     old_cisb_auto,                      // which we have to modify and put
  52.     old_zmod_auto,                      // back to what they were when done
  53.     old_sound;
  54. str old_down_dir[64],
  55.     old_up_dir[64],
  56.     old_usage_fname[64];
  57.  
  58. //////////////////////////////////////////////////////////////////////////////
  59. //////////////////////////////////////////////////////////////////////////////
  60.  
  61. main()
  62.  
  63. {
  64.  int c;
  65.  
  66.  clear_scr();
  67.  
  68.  if (read_host_config_file() == -1)
  69.   {
  70.    prints("Unable to read QDHOST.CNF...");
  71.    prints("Running QDCONFIG, the Host Mode configuration script.^M^J");
  72.    call("QDCONFIG");
  73.    if (read_host_config_file() == -1)
  74.     {
  75.      prints("Still unable to read QDHOST.CNF. Aborting Host Mode.^M^J");
  76.      return -1;
  77.     }
  78.   }
  79.  
  80.  if (!check_directories())
  81.   {
  82.    prints("Either the upload or download directory as defined in the QDHOST.CNF file");
  83.    prints("doesn't exist. Either create the missing directory with the DOS 'MKDIR'");
  84.    prints("command, or run the QDCONFIG script to redefine what directories to use.");
  85.    prints("Aborting Host Mode.");
  86.    return -1;
  87.   }
  88.  
  89.  old_scr_chk_key = _scr_chk_key;
  90.  _scr_chk_key = 0;
  91.  old_cisb_auto = _cisb_auto;
  92.  _cisb_auto = 0;
  93.  old_zmod_auto = _zmod_auto;
  94.  _zmod_auto = 0;
  95.  old_sound = _sound_on;
  96.  _sound_on = 0;
  97.  old_down_dir = _down_dir;
  98.  _down_dir = host_uploads;   // these are reversed because we are now the Host
  99.  old_up_dir = _up_dir;
  100.  _up_dir = host_downloads;   // these are reversed because we are now the Host
  101.  old_usage_fname = _usage_fname;
  102.  
  103.  usagelog("QDHOST.LOG");
  104.  
  105.  if (direct_connect)
  106.   carrier_counts = 0;
  107.  else
  108.   carrier_counts = 1;
  109.  
  110.  if (!direct_connect && carrier())
  111.   already_connected = 1;
  112.  
  113.  
  114.  while (1)
  115.   {
  116.    if (!direct_connect && !already_connected)
  117.     {
  118.      if (!modem_lock)
  119.         set_cparams(modem_lock, 0, 8, 1);
  120.      delay(3);
  121.      prints("Sending Modem Init string...");
  122.      cputs_tr(_mdm_init_str);
  123.      delay(10);
  124.      prints("Sending Auto-Answer string...");
  125.      cputs_tr(_auto_ans_str);
  126.     }
  127.  
  128.    finished_caller = kill_user = 0;
  129.  
  130.    if (direct_connect)
  131.     carrier_counts = 0;
  132.    else
  133.     carrier_counts = 1;
  134.  
  135.    if (!direct_connect)
  136.     {
  137.      prints("^M^JQDHost Mode: Waiting for call...");
  138.      prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
  139.  
  140.      do
  141.       {
  142.        if (carrier())
  143.         {
  144.          local_mode = 0;
  145.          break;
  146.         }
  147.  
  148.        c = inkey();
  149.        if (c)
  150.         {
  151.          if (c == 27)
  152.           {
  153.            exit_requested = 1;
  154.            break;
  155.           }
  156.          else if (c == 'l' || c == 'L')               // local teswt mode
  157.           {
  158.            prints("Local test mode entered");
  159.            local_mode = 1;
  160.            carrier_counts = 0;
  161.           }
  162.         }
  163.       }
  164.      while (toupper(c) != 'L');
  165.     }
  166.  
  167.    if (!exit_requested)
  168.     {
  169.      prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
  170.  
  171.      do_one_caller();
  172.      if ((connection_lost || kill_user) && carrier_counts && carrier())
  173.       hangup();             // make sure nobody sneaks in
  174.     }
  175.    already_connected = 0;
  176.    if (exit_requested)
  177.     {
  178.      if (!carrier() && !direct_connect)
  179.       {
  180.        prints("Sending Modem Init string...");
  181.        cputs_tr(_mdm_init_str);
  182.       }
  183.      _scr_chk_key = old_scr_chk_key;
  184.      _cisb_auto = old_cisb_auto;
  185.      _zmod_auto = old_zmod_auto;
  186.      _sound_on = old_sound;
  187.      _down_dir = old_down_dir;
  188.      _up_dir = old_up_dir;
  189.      prints("^M^JQDHost mode script finished.");
  190.      usagelog("*CLOSE*");
  191.      _usage_fname = old_usage_fname;
  192.      return 1;
  193.     }
  194.   }
  195. }
  196.  
  197. //////////////////////////////////////////////////////////////////////////////
  198.  
  199. HelpOn(int option)
  200.  
  201. {
  202.    if (option == 'H')
  203.     {
  204.      host_send("^M^JHelp on Help^M^J");
  205.      host_send("^M^JTo use the help, simply type the first letter of one of the following:");
  206.      host_send("^M^J^M^J<H>elp <F>iles <T>ype <U>pload <D>ownload <S>hell <C>hat <G>oodbye");
  207.      Host_send("^M^J");
  208.     }
  209.    if (option == 'F')
  210.     {
  211.      host_send("^M^JHelp on Files^M^J");
  212.      host_send("^M^JThe 'Files' option allows the caller to list the files in the");
  213.      host_send("^M^Jcurrent disk directory. The caller must press a key after each");
  214.      host_send("^M^Jscreen. The output is not echoed on the local screen. If the");
  215.      host_send("^M^Jcaller has access level two s/he is prompted for a filespec,");
  216.      host_send("^M^Jwhich may include the * and ? wildcard characters (see your");
  217.      host_send("^M^JDOS manual), so that the contents of other directories than");
  218.      host_send("^M^Jthe 'Host download dir' may be listed.");
  219.      Host_send("^M^J");
  220.     }
  221.    if (option == 'T')
  222.     {
  223.      host_send("^M^JHelp on Type^M^J");
  224.      host_send("^M^JThe 'Type' option allows the caller to view any ASCII file in");
  225.      host_send("^M^Jthe Host Download Directory, or in any directory for access");
  226.      host_send("^M^JLevel 2 callers.   Simply give the name (or full path and name)");
  227.      host_send("^M^Jof the system file you wish to view:    ie. C:\TELIX\TELIX.IMG");
  228.      Host_send("^M^J");
  229.     }
  230.    if (option == 'U')
  231.     {
  232.      host_send("^M^JHelp on Uploading^M^J");
  233.      host_send("^M^JThe 'Upload' option allows the caller to send a file to the");
  234.      host_send("^M^Jhost. The caller is shown the a menu of protocols.   He/she");
  235.      host_send("^M^Jshould select the appropriate protocol by its first letter");
  236.      host_send("^M^J(or 'E' for Ymodem-g). If appropriate the caller is also asked");
  237.      host_send("^M^Jfor the filename.  The transfer is then initiated by QDHOST.  The");
  238.      host_send("^M^Jcaller must then initiate the upload on THEIR side by giving");
  239.      host_send("^M^Jtheir comm program an upload instruction, choosing the same");
  240.      host_send("^M^Jprotocol as they told host, and giving the filename again,");
  241.      host_send("^M^Jwithin 60 seconds of telling QDHOST the same information.");
  242.      Host_send("^M^J");
  243.     }
  244.    if (option == 'D')
  245.     {
  246.      host_send("^M^JHelp on Downloading^M^J");
  247.      host_send("^M^JThe 'Download' command allows a caller to receive a file from");
  248.      host_send("^M^Jthe host. The caller must select the protocol after giving the");
  249.      host_send("^M^Jdownload command to QDHOST, and then must tell QDHOST what files");
  250.      host_send("^M^Jto send.    Some protocols like ZModem will start automatically");
  251.      host_send("^M^Jafter this.   Others, like XModem, require the caller to start");
  252.      host_send("^M^Ja download in their comm program at this point (usually Pg-Dn)");
  253.      host_send("^M^Jand will be asked by the comm program for a file name again.  The");
  254.      host_send("^M^Jtransfer is then initiated.");
  255.      Host_send("^M^J");
  256.     }
  257.    if (option == 'S')
  258.     {
  259.      host_send("^M^JHelp on Shelling^M^J");
  260.      host_send("^M^JThe 'Shell' command is a very powerful but also very dangerous");
  261.      host_send("^M^Jcommand. It allows the caller to run a DOS shell on the sys-");
  262.      host_send("^M^Jtem, except that the caller receives the output, and the");
  263.      host_send("^M^Jcaller enters the keystrokes.   The caller has complete control");
  264.      host_send("^M^Jof the HOST system at the DOS level.   Shell is a password");
  265.      host_send("^M^Jprotected feature of QDHOST.  The caller sees program output only");
  266.      host_send("^M^Jif the programs use standard DOS output. Programs that write");
  267.      host_send("^M^Jdirectly to the video screen will work, but will not be seen");
  268.      host_send("^M^Jby the remote caller. As well, programs that use non-DOS meth-");
  269.      host_send("^M^Jods of getting keystrokes will not receive the callers");
  270.      host_send("^M^Jkeystrokes. Finally, under some systems, if the caller presses");
  271.      host_send("^M^JBackspace at the DOS prompt when the current line is empty,");
  272.      host_send("^M^JDOS will hang on the Host machine. As these are functions of");
  273.      host_send("^M^JDOS, there is nothing that can be done about these limits.");
  274.      Host_send("^M^J");
  275.     }
  276.    if (option == 'C')
  277.     {
  278.      host_send("^M^JHelp on Chatting^M^J");
  279.      host_send("^M^JThe 'Chat' command allows the caller to chat with the host op-");
  280.      host_send("^M^Jerator. When the caller presses 'C' the host operator is paged");
  281.      host_send("^M^Jfor 20 seconds.    If the host operator responds, you will see");
  282.      host_send("^M^Jhim/her typing on your screen.    If you can, place yourself in");
  283.      host_send("^M^JChat Mode, by using your comm program's chat mode (Telix's is");
  284.      host_send("^M^JAlt-Y).   You will then see what you type on half of the screen");
  285.      host_send("^M^Jand the operator's words on the other half.");
  286.      Host_send("^M^J");
  287.     }
  288.    if (option == 'G')
  289.     {
  290.      host_send("^M^JHelp on Goodbye^M^J");
  291.      host_send("^M^JThe 'Goodbye' command allows the caller to log off the host");
  292.      Host_send("^M^J");
  293.     }
  294. }
  295.  
  296. //////////////////////////////////////////////////////////////////////////////
  297.  
  298. do_one_caller()
  299.  
  300. {
  301.  str strn[80],
  302.      fname[64];
  303.  int option,
  304.      status,
  305.      c, i, i2, f;
  306.  
  307.  access_level = 1;
  308.  
  309.  if (already_connected)
  310.   prints("Already connected, or modem Carrier Detect switch improperly set!");
  311.  else if (carrier_counts)
  312.   {
  313.    if (!modem_lock)
  314.     if (!determine_baud())
  315.     ;                          // do something else here if this is a problem
  316.   }
  317.  
  318.  delay(10);
  319.  type_file("LOGO.MSG");
  320.  
  321.  flushbuf();
  322.  while (1)
  323.   {
  324.    host_send("Please enter your full name: ");
  325.    host_input_strn(current_caller, 30, 1);
  326.    host_send("^M^J");
  327.  
  328.    if (finished_caller)
  329.     return;
  330.  
  331.    if (strlen(current_caller) >= 5)
  332.     break;
  333.   }
  334.  
  335.  access_level = ask_for_pass(3, pass1, pass2);
  336.  
  337.  if (access_level)
  338.   ustamp("Logon by ", 1, 0);
  339.  else
  340.   ustamp("Failed logon attempt by ", 1, 0);
  341.  ustamp(current_caller, 0, 1);
  342.  
  343.  if (!access_level)
  344.   {
  345.    host_send("Goodbye!^M^J");
  346.    if (carrier_counts)
  347.     {
  348.      delay(10);
  349.      hangup();
  350.     }
  351.    return;
  352.   }
  353.  
  354.  type_file("WELCOME.MSG");
  355.  
  356.  while (1)
  357.   {
  358.    if (finished_caller)
  359.     return;
  360.  
  361.    host_send("^M^JCommand: Help  Files  Type  Upload  Download  Shell  Chat  Goodbye ? ");
  362.    host_input_strn(strn, 1, 1);
  363.    option = toupper(subchr(strn, 0));
  364.    host_send("^M^J");
  365.  
  366.    if (option == 'H')
  367.     {
  368.      host_send("^M^J^M^JWhich item above do you wish help on? ");
  369.      host_input_strn(strn, 1, 1);
  370.      Option = toupper(subchr(strn, 0));
  371.      Host_send("^M^J");
  372.      HelpOn(Option);
  373.      Option = 'H';
  374.     }
  375.    if (option == 'F')                 // Files directory
  376.     {
  377.      if (access_level == 2)
  378.       {
  379.        host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
  380.        host_input_strn(fname, 64, 1);
  381.        host_send("^M^J");
  382.  
  383.        if (just_filename(fname))
  384.         {
  385.          strn = host_downloads;
  386.          strcat(strn, fname);
  387.         }
  388.        else
  389.         strn = fname;
  390.       }
  391.      else
  392.       {
  393.        strn = host_downloads;
  394.        strcat(strn, "*.*");
  395.       }
  396.        
  397.      if (local_mode)
  398.       show_directory(strn, 0, carrier_counts);
  399.      else
  400.       show_directory(strn, 1, carrier_counts);
  401.      host_send("^M^J");
  402.     }
  403.    else if (option == 'T')            // Type a file
  404.     {
  405.      host_send("Type what file? ");
  406.      host_input_strn(strn, 64, 1);
  407.      host_send("^M^J");
  408.      if (access_level != 2)             // if access 1, name and ext only
  409.       fnstrip(strn, 3, fname);
  410.      else
  411.       fname = strn;
  412.  
  413.      if (just_filename(fname))
  414.       {
  415.        strn = host_downloads;
  416.        strcat(strn, fname);
  417.        fname = strn;
  418.       }
  419.  
  420.      if (!filefind(fname, 0, strn))
  421.       {
  422.        host_send("Unable to find ");
  423.        host_send(fname);
  424.        continue;
  425.       }
  426.  
  427.      type_file(fname);
  428.     }
  429.    else if (option == 'G')            // Goodbye (Hang-up)
  430.     {
  431.      host_send("^M^JGoodbye!^M^J");
  432.      ustamp("User logged off.", 1, 1);
  433.      if (carrier_counts)
  434.       {
  435.        delay(10);
  436.        hangup();
  437.       }
  438.      return;
  439.     }
  440.    else if (option == 'C')            // Chat mode
  441.     {
  442.      prints("Sysop: Press Space to chat, any other key not to.^M^J");
  443.      c = 0;
  444.      _sound_on = 1;
  445.      for (i = 8; i && !c; --i)
  446.       {
  447.        if (carrier_counts && !carrier())
  448.         {
  449.          prints("^M^JConnection has been lost, call terminated.^M^J");
  450.          connection_lost = 1;
  451.          finished_caller = 1;
  452.          break;
  453.         }
  454.        cputc('^G');
  455.        tone(523, 20);
  456.        tone(659, 20);
  457.        tone(523, 20);
  458.        tone(659, 20);
  459.        tone(523, 20);
  460.        tone(659, 20);
  461.        for (i2 = 30; i2 && (c = inkey()) == 0; --i2)
  462.         delay(1);
  463.       }
  464.      _sound_on = 0;
  465.      if (finished_caller)
  466.       continue;
  467.      if (c != ' ' || !c)
  468.       {
  469.        host_send("Sorry, the Sysop is unavailable^M^J");
  470.        continue;
  471.       }
  472.      host_send("The sysop is here!^M^J");
  473.      chatmode(1);
  474.     }
  475.    else if (option == 'U')            // User upload
  476.     {
  477.      option = host_get_prot();
  478.      if (!option)
  479.       continue;
  480.  
  481.      status = 1;
  482.      if (option == 'T' || option == 'M' || option == 'S' ||
  483.          option == 'Y' || option == 'Z' || option == 'E')
  484.       {
  485.        send_transfer_msg();
  486.        status = receive(option, "");
  487.       }
  488.      else
  489.       {
  490.        host_send("Upload what file? ");
  491.        host_input_strn(strn, 48, 1);
  492.        host_send("^M^J");
  493.        if (!strn)
  494.         continue;
  495.        if (access_level != 2)             // if access 1, name and ext only
  496.         fnstrip(strn, 3, fname);
  497.        else
  498.         fname = strn;
  499.  
  500.        if (just_filename(fname))
  501.         {
  502.          strn = host_uploads;
  503.          strcat(strn, fname);
  504.          fname = strn;
  505.         }
  506.  
  507.        if (filefind(fname, 23, strn))
  508.         host_send("File already exists!^M^J");
  509.        else
  510.         {
  511.          send_transfer_msg();
  512.          status = receive(option, fname);
  513.         }
  514.       }
  515.      if (status == -2)                        // Carrier lost
  516.       connection_lost = finished_caller = 1;
  517.      else if (status == -1)
  518.       host_send("^GOne or more files not received!^M^J");
  519.     }
  520.    else if (option == 'D')            // User download
  521.     {
  522.      option = host_get_prot();
  523.      if (!option)
  524.       continue;
  525.      host_send("Download what file(s)? ");
  526.      host_input_strn(strn, 48, 1);
  527.      host_send("^M^J");
  528.      if (!strn)
  529.       continue;
  530.      if (access_level != 2)      // if not level 2, keep only name & ext
  531.       fnstrip(strn, 3, fname);
  532.      else
  533.       fname = strn;
  534.  
  535.      if (just_filename(fname))
  536.       {
  537.        strn = host_downloads;
  538.        strcat(strn, fname);
  539.        fname = strn;
  540.       }
  541.  
  542.      if (!filefind(fname, 0, strn))
  543.       {
  544.        host_send("Unable to find any matching file(s)!^M^J");
  545.        continue;
  546.       }
  547.  
  548.      status = 1;
  549.      send_transfer_msg();
  550.      status = send(option, fname);
  551.      if (status == -2)                        // Carrier lost
  552.       connection_lost = finished_caller = 1;
  553.      else if (status == -1)
  554.       host_send("^GOne or more files not received!^M^J");
  555.     }
  556.    else if (option == 'S')            // Remote shell
  557.     {
  558.      if (ask_for_pass(3, shellpass, shellpass) != 0)
  559.       {
  560.        host_send("Type EXIT and then press Enter to come back.^M^J");
  561.        if (get_baud() == 300)
  562.         delay(10);
  563.        if (local_mode)
  564.         dos("", 0);
  565.                  // See if user has prepared a custom file for shell operation
  566.                  // and call that if it exists
  567.        else if (filefind("RSHELL.BAT", 0, strn))
  568.         dos("RSHELL.BAT", 0);
  569.        else   // otherwise make our own temporary batch file for redirection
  570.         {
  571.          // now want to make a temporary batch file which will be called
  572.          // to redirect DOS input and output, then shell to another copy
  573.          // of COMMAND.COM
  574.          f = fopen("HOSTTEMP.BAT", "w");
  575.          if (f)
  576.           {
  577.            if (get_port() != 1 && get_port() != 2)
  578.             {
  579.              host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
  580.              continue;
  581.             }
  582.  
  583.            strn = "COMx";
  584.            setchr(strn, 3, get_port() + '0'); // get right name to redirect
  585.  
  586.            fputs("CTTY ", f);           // write to batch file
  587.            fputs(strn, f);
  588.            fputs("^M^JCOMMAND^M^J", f);
  589.            fputs("CTTY CON^M^J", f);
  590.            fputs("EXIT^M^J", f);
  591.  
  592.            fclose(f);                   // close the file
  593.  
  594.            if (!local_mode)             // call batch file
  595.             dos("HOSTTEMP.BAT", 0);
  596.           }
  597.          else
  598.           host_send("Can't open temporary batch file!^M^J");
  599.         }
  600.       }
  601.     }
  602.    else if (option == '^Z')            // Shut down Host Mode
  603.     {
  604.      host_send("Shut down QDHost mode. ");
  605.      if (!ask_for_pass(3, shutpass, shutpass))
  606.       continue;
  607.      host_send("Goodbye!^M^J");
  608.      if (carrier_counts)
  609.       hangup();
  610.      ustamp("User shut down QDHost Mode.", 1, 1);
  611.      finished_caller = 1;
  612.      exit_requested = 1;
  613.     }
  614.   }
  615. }
  616.  
  617. //////////////////////////////////////////////////////////////////////////////
  618.  
  619. host_get_prot()
  620.  
  621. {
  622.  str prot[1];
  623.  
  624.  host_send("^M^JModem7  SEAlink  Xmodem  1k-Xmodem  G-1k-Xmodem  Ymodem  YmodEm-g  Zmodem^M^J");
  625.  host_send("Which protocol? ");
  626.  host_input_strn(prot, 1, 1);
  627.  host_send("^M^J");
  628.  
  629.  if (strposi("MSX1GYEZ", prot, 0) == -1)     // if illegal prot
  630.   prot = "";                                 // return 0
  631.  
  632.  return (toupper(subchr(prot, 0)));
  633.  
  634. }
  635.  
  636. //////////////////////////////////////////////////////////////////////////////
  637.  
  638. send_transfer_msg()
  639.  
  640. {
  641.  host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
  642. }
  643.  
  644. //////////////////////////////////////////////////////////////////////////////
  645. // Determine the baud rate once a Carrier Detect Signal has been detected
  646. // Since no characters were read, the 'CONNECT' string should still be
  647. // in the receive buffer.
  648.  
  649. determine_baud()
  650.  
  651. {
  652.  int t3, t12, t24, t96, t192;
  653.  int tmark, stat;
  654.  int new_baud = 0;
  655.  
  656.  printsc("Determining baud... ");
  657.  
  658.  track_free(0);                // clear all existing tracks
  659.  
  660.  t3 = track(conn300, 0);       // check for connect strings
  661.  t12 = track(conn1200, 0);
  662.  t24 = track(conn2400, 0);
  663.  t96 = track(conn9600, 0);
  664.  t192 = track(conn19200, 0);
  665.  
  666.  tmark = timer_start(30);      // wait up to 3 seconds for string
  667.                              
  668.  while (!time_up(tmark))
  669.   {
  670.    if (!carrier())
  671.     {
  672.      track_free(0);            // clear all existing tracks
  673.      timer_free(tmark);        // free existing timer
  674.      return 0;
  675.     }
  676.  
  677.    if (cinp_cnt())
  678.     track_addchr(cgetc());
  679.  
  680.    stat = track_hit(0);
  681.    if (stat == 0)
  682.     continue;
  683.  
  684.    if (stat == t3)
  685.     new_baud = 300;
  686.    else if (stat == t24)
  687.     new_baud = 2400;
  688.    else if (stat == t96)
  689.     new_baud = 9600;
  690.    else if (stat == t192)
  691.     new_baud = 19200;
  692.    else
  693.     new_baud = 1200;
  694.  
  695.    break;                      // have baud rate, get out
  696.   }
  697.  
  698.  track_free(0);                // clear all existing tracks
  699.  timer_free(tmark);            // free existing timer
  700.  
  701.  if (!new_baud)                // time-up without CONNECT string
  702.   {
  703.    prints("Failed!");
  704.    return 0;     
  705.   }
  706.  
  707.  printn(new_baud);
  708.  prints("");
  709.  set_cparams(new_baud, get_parity(), get_datab(), get_stopb());
  710.  
  711.  return 1;                     // indicate success
  712.  
  713. }
  714.  
  715. //////////////////////////////////////////////////////////////////////////////
  716.  
  717. type_file(str fname)
  718.  
  719. {
  720.  int f;
  721.  str buf[100];
  722.  int ichar, lines_sent = 0;
  723.  
  724.  f = fopen(fname, "r");
  725.  if (!f)
  726.   return -1;
  727.  
  728.  host_send("^M^J");
  729.  
  730.  while (1)
  731.   {
  732.    if (carrier_counts)
  733.     if (!carrier())
  734.      {
  735.       connection_lost = 1;
  736.       finished_caller = 1;
  737.       fclose(f);
  738.       return 0;
  739.      }
  740.  
  741.    if (fgets(buf, 80, f) == -1)
  742.     {
  743.      fclose(f);
  744.      return 1;
  745.     }
  746.  
  747.    host_send(buf);
  748.    host_send("^M^J");
  749.    ++lines_sent;
  750.  
  751.    if (lines_sent >= 22)
  752.     {
  753.      lines_sent = 0;
  754.      host_send("[More]");
  755.      host_input(1);
  756.  
  757.      if (finished_caller)         // if user inactivity
  758.       {
  759.        fclose(f);
  760.        return 0;
  761.       }
  762.  
  763.      host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
  764.     }
  765.  
  766.    while (cinp_cnt())
  767.     {
  768.      ichar = cgetc();
  769.      if (ichar == '^C' || ichar == '^K')
  770.       {
  771.        host_send("^M^J");
  772.        fclose(f);
  773.        return 1;
  774.       }
  775.     }
  776.   }
  777. }
  778.  
  779. //////////////////////////////////////////////////////////////////////////////
  780.  
  781. host_send(str outstr)
  782.  
  783. {
  784.  
  785.  printsc(outstr);
  786.  if (!local_mode)
  787.   cputs(outstr);
  788.  
  789. }
  790.  
  791. //////////////////////////////////////////////////////////////////////////////
  792.  
  793. host_send_c(int chr)
  794.  
  795. {
  796.  
  797.  printc(chr);
  798.  if (!local_mode)
  799.   cputc(chr);
  800.  
  801. }
  802.  
  803. //////////////////////////////////////////////////////////////////////////////
  804.  
  805. host_input_strn(str buf, int maximum, int echoable)
  806.  
  807. {
  808.  int i = 0, key;
  809.  
  810.  while (1)
  811.   {
  812.    key = host_input(echoable);
  813.    if (!key)                 // timeout or user disconnect
  814.     {
  815.      setchr(buf, 0, 0);      // set string to empty
  816.      return 0;               // indicate there is a problem
  817.     }
  818.  
  819.    if (key == '^M')
  820.     break;
  821.    if (key == 127 || key == 8)
  822.     {
  823.      if (i)
  824.       {
  825.        --i;
  826.          host_send_c(key);
  827.       }
  828.      continue;
  829.     }
  830.    if (i < maximum)
  831.     {
  832.      setchr(buf, i, key);
  833.      i = i + 1;
  834.     }
  835.    else
  836.     i = i + 1;
  837.   }
  838.  
  839.  if (i > maximum)
  840.   i = maximum;
  841.  
  842.  setchr(buf, i, '^0');
  843.  
  844.  if (subchr(buf, 0))
  845.   return 1;
  846.  else
  847.   return 0;
  848.  
  849. }
  850.  
  851. //////////////////////////////////////////////////////////////////////////////
  852.  
  853. host_input(int echoable)
  854.  
  855. {
  856.  int c;
  857.  int t;
  858.  
  859.  t = timer_start(2400);         // 4 minutes inactivity allowed
  860.  
  861.  while (1)
  862.   {
  863.    if (time_up(t) && !direct_connect)
  864.     {
  865.      host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
  866.      if (carrier_counts)
  867.       hangup();
  868.      finished_caller = 1;
  869.      kill_user = 1;
  870.      break;
  871.     }
  872.  
  873.    if (carrier_counts)
  874.     if (!carrier())
  875.       {
  876.        prints("^M^JConnection has been lost, call terminated.^M^J");
  877.        connection_lost = 1;
  878.        finished_caller = 1;
  879.        break;
  880.       }
  881.  
  882.    if ((c = inkey()) != 0)
  883.     {
  884.      if (c == 27)               // ESC key, sysop wants to exit
  885.       {
  886.        finished_caller = 1;
  887.        exit_requested = 1;
  888.        break;
  889.       }
  890.      else if (c == 0x4f00)      // END key, temrinate user
  891.       {
  892.        prints("^M^JUser terminated!");
  893.        ustamp("User terminated!", 1, 1);
  894.        if (carrier_counts)
  895.         hangup();
  896.  
  897.        finished_caller = 1;
  898.        kill_user = 1;
  899.        break;
  900.       }
  901.  
  902.      else if (c <= 255)
  903.       {
  904.        if (c != 8 && c != 127)   
  905.         if (!echoable)
  906.          host_send_c('*');
  907.         else
  908.          host_send_c(c);
  909.        break;
  910.       }
  911.     }
  912.  
  913.    if (!local_mode)
  914.     if (cinp_cnt())
  915.      {
  916.       c = cgetc();
  917.       if (c != 8 && c != 127)
  918.        if (!echoable)
  919.         host_send_c('*');
  920.        else
  921.         host_send_c(c);
  922.       break;
  923.      }
  924.   }
  925.  
  926.  timer_free(t);                 // free existing timer
  927.  if (finished_caller)
  928.    return 0;                    // return 0 - no character
  929.  
  930.  return c;                      // return received/pressed character
  931. }
  932.  
  933. //////////////////////////////////////////////////////////////////////////////
  934.  
  935. ask_for_pass(int maxtries, str pass1, str pass2)
  936.  
  937. {
  938.  int i;
  939.  str strn[8];
  940.  
  941.  for (i = 0; i < maxtries; ++i)
  942.   {
  943.    if (i)
  944.     host_send("Wrong! Try again.^M^J");
  945.    host_send("Password: ");
  946.    host_input_strn(strn, 8, 0);
  947.    host_send("^M^J");
  948.  
  949.    if (finished_caller)
  950.     return 0;
  951.  
  952.    if (!strcmpi(strn, pass1))
  953.     return 1;
  954.  
  955.    if (!strcmpi(strn, pass2))
  956.     return 2;
  957.   }
  958.  
  959.  host_send("No more chances. Access denied.^M^J");
  960.  
  961.  return 0;
  962.  
  963. }
  964.  
  965. //////////////////////////////////////////////////////////////////////////////
  966.  
  967. read_host_config_file()
  968.  
  969. {
  970.  str s[80];
  971.  int f, stat;
  972.  
  973.  s = _telix_dir;
  974.  strcat(s, "QDHOST.CNF");
  975.  
  976.  f = fopen(s, "r");
  977.  if (!f)
  978.   {
  979.    printsc("Can't open ");
  980.    prints(s);
  981.    return -1;
  982.   }
  983.  
  984.  stat = fgets(s, 80, f);
  985.  if (stat == -1)
  986.   goto got_error;
  987.  pass1 = s;
  988.  
  989.  stat = fgets(s, 80, f);
  990.  if (stat == -1)
  991.   goto got_error;
  992.  pass2 = s;
  993.  
  994.  stat = fgets(s, 80, f);
  995.  if (stat == -1)
  996.   goto got_error;
  997.  shellpass = s;
  998.  
  999.  stat = fgets(s, 80, f);
  1000.  if (stat == -1)
  1001.   goto got_error;
  1002.  shutpass = s;
  1003.  
  1004.  stat = fgets(s, 80, f);
  1005.  if (stat == -1)
  1006.   goto got_error;
  1007.  host_downloads = s;
  1008.  
  1009.  stat = fgets(s, 80, f);
  1010.  if (stat == -1)
  1011.   goto got_error;
  1012.  host_uploads = s;
  1013.  
  1014.  stat = fgets(s, 80, f);
  1015.  if (stat == -1)
  1016.   goto got_error;
  1017.  direct_connect = (toupper(subchr(s, 0)) == 'D');
  1018.  
  1019.  stat = fgets(s, 80, f);
  1020.  if (stat == -1)
  1021.   goto got_error;
  1022.  modem_lock = stoi(s);
  1023.  
  1024.  fclose(f);
  1025.  return 1;
  1026.  
  1027. // jump here if error
  1028.  
  1029.  got_error:
  1030.   fclose(f);
  1031.   return -1;
  1032.  
  1033. }
  1034.  
  1035. //////////////////////////////////////////////////////////////////////////////
  1036.  
  1037. check_directories()
  1038.  
  1039. {
  1040.  str s[80];
  1041.  int i, a;
  1042.  
  1043.  // first remove trailing slashes
  1044.  
  1045.  s = host_uploads;
  1046.  i = strlen(s);
  1047.  if (i > 0)
  1048.   if (subchr(s, i - 1) == '\' || subchr(s, i - 1) == '/')
  1049.    setchr(s, i - 1, 0);
  1050.  if (s && !(strlen(s) == 2 && subchr(s, 1) == ':'))
  1051.   {
  1052.    a = fileattr(s);
  1053.    if (a == -1 || !(a & 16))
  1054.     return 0;                  // not a directory or doesn't exist
  1055.   }
  1056.  
  1057.  s = host_downloads;
  1058.  i = strlen(s);
  1059.  if (i > 0)
  1060.   if (subchr(s, i - 1) == '\' || subchr(s, i - 1) == '/')
  1061.    setchr(s, i - 1, 0);
  1062.  if (s && !(strlen(s) == 2 && subchr(s, 1) == ':'))
  1063.   {
  1064.    a = fileattr(s);
  1065.    if (a == -1 || !(a & 16))
  1066.     return 0;                  // not a directory or doesn't exist
  1067.   }
  1068.  
  1069.  return 1;
  1070.  
  1071. }
  1072.  
  1073. //////////////////////////////////////////////////////////////////////////////
  1074. // returns TRUE if passed filespec is just a filename. Also handles the
  1075. // forward slash as a path separator.
  1076.  
  1077. just_filename(str filespec)
  1078.  
  1079. {
  1080.  int slash, space;
  1081.  
  1082.  if (strpos(filespec, ":", 0) != -1)
  1083.   return 0;
  1084.  if (strpos(filespec, "\", 0) != -1)
  1085.   return 0;
  1086.  if ((slash = strpos(filespec, "/")) == -1)
  1087.   return 1;
  1088.  
  1089.  space = strpos(filespec, " ");
  1090.  if (space == -1)
  1091.   return 0;
  1092.  if (space < slash)
  1093.   return 1;
  1094.  
  1095.  return 0;
  1096.  
  1097. }
  1098.  
  1099. //////////////////////////////////////////////////////////////////////////////
  1100.